var interface = require('./collectors/interface'),
    eventstream = require('./eventstream'),
    pipeline = require('./pipeline'),
    persist = require('./persist');
process.mixin(GLOBAL, require('sys'), require('./tools'));

//GLOBAL.DEBUG=true;

/**
 * Size is in seconds
 */
var windowAvg = function(size, callback) {
  var state = {};
  var window = 0;

  return function(e) {
    var result = {};
    var ts = new Date().getTime();
    var newwindow = (ts - (ts%(size*1000)));

    if(newwindow > window) { //We've entered a new window, reset state
      window = newwindow;
      state = {}; 
    }

    //Loop through each value of the events data
    for(p in e.data) {
      //initialize the state if needed
      if(!state[p]) {
        state[p] = {
          count: 0,
          sum: 0,
        };
      }

      //Calculate the new values  
      state[p].count += 1;
      state[p].sum += e.data[p];

      //Add the average to the current result
      result[p] = state[p].sum/state[p].count;
    }

    if(callback && typeof(callback) === 'function') {
      callback.call(this, {
        createtime: new Date().getTime(),
        elapsedtime: 0,
        name: 'windowavg',
        window: window,
        data: result
      });
    }

  };
};

/**
 *
 */
var runningAvg = function(callback) {
  var state = {};

  return function(e) {
    var result = {};

    //Loop through each value of the events data
    for(p in e.data) {
      //initialize the state if needed
      if(!state[p]) {
        state[p] = {
          count: 0,
          sum: 0,
        };
      }

      //Calculate the new values  
      state[p].count += 1;
      state[p].sum += e.data[p];

      //Add the average to the current result
      result[p] = state[p].sum/state[p].count;
    }

    if(callback && typeof(callback) === 'function') {
      callback.call(this, {
        createtime: new Date().getTime(),
        elapsedtime: 0,
        name: 'runningavg',
        data: result
      });
    }
  };
};

/**
 *
 */
var runningMax = function(callback) {
  var state = {};

  return function(e) {
    var result = {};

    //Loop through each value of the events data
    for(p in e.data) {
      //initialize the state if needed
      if(!state[p]) {
        state[p] = 0;
      }

      //Calculate the new values  
      if(e.data[p] > state[p]) {
        state[p] = e.data[p];
      }

      result[p] = state[p];
    }

    if(callback && typeof(callback) === 'function') {
      callback.call(this, {
        createtime: new Date().getTime(),
        elapsedtime: 0,
        name: 'runningmax',
        data: result
      });
    }
  };
};

/**
 * 
 */
var runningMin = function(callback) {
  var state = {};

  return function(e) {
    var result = {};
    
    for(p in e.data) {
      //initialize the state if needed
      if(!state[p]) {
        state[p] = 0;
      }

      //Calculate the new values  
      if(state[p] === 0 || (e.data[p] !==0 && e.data[p] < state[p])) {
        state[p] = e.data[p];
      }

      //Add the average to the current result
      result[p] = state[p];
    }

    if(callback && typeof(callback) === 'function') {
      callback.call(this, {
        createtime: new Date().getTime(),
        elapsedtime: 0,
        name: 'runningmin',
        data: result
      });
    }
  };
};

/**
 *
 */
var tee = function() {
  var functions = Array.prototype.slice.call(arguments);

  return function(e) {
    for(var i=0;i<functions.length;i++) {
      functions[i].call(this, e);
    }
  };
};

/**
 *
 */
var log = function() {
  return function(e) {
    puts("log:"+inspect(e));
    puts("this:"+inspect(this));
    return e;
  };
};

/**
 */
persist.start(function(client) {

  /*
   */
  new eventstream.IntervalEventSource( {
    id: 'b8bf098a-0cde-4985-bac5-9c735d5f298b', //A unique ID to identify this data source globally
    name: 'eth0_collector', //A pretty name to display to humans
    source: interface.getInterfaceStats('eth0'), //Function that is run on the specified interval and outputs data via a callback
    handler: new pipeline.Pipeline( [
          persist.push( {conn: client, key: 'data'}),
          persist.trim( {conn: client, key: 'data', max: 100 })
        ]).start,

      /*
      tee( //The callback to execute when the source provides data
      persist.push(client, {
          key: 'data',
          callback: persist.trim(client, {
            key: 'data',
            max: 100
          })
        }
      ),
      runningAvg( 
        persist.set(client, {
          key: 'avg',
          attrib: 'data'
        })
      ),
      runningMax( 
        persist.set(client, {
          key: 'max',
          attrib: 'data'
        })
      ),
      runningMin(
        persist.set(client, {
          key: 'min',
          attrib: 'data'
        })
      ),
      //windowAvg(60,
        log()
        //persist.eventDataSetAdd(client, 'avg:1min', 'window')
      //)
    )),
      */
    interval: 1 //Run every second
  }).addListener('runcount', persist.set(client,{
      key:'runcount',
      attrib: 'data'
    })).addListener('state', persist.set(client, {
      key: 'state',
      attrib: 'data'
    })).start();

});
